package com.quectel.taskserver.job.scheduling;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.quectel.constant.core.scheduling.SchedulingAttendanceDailyConstants;
import com.quectel.constant.global.SystemConstants;
import com.quectel.core.module.scheduling.dto.SchedulingAttendanceDailyDto;
import com.quectel.core.module.scheduling.dto.SchedulingAttendanceMonthDto;
import com.quectel.core.module.scheduling.service.SchedulingAttendanceDailyService;
import com.quectel.core.module.scheduling.service.SchedulingAttendanceGroupPersonBindingService;
import com.quectel.core.module.scheduling.service.SchedulingAttendanceGroupService;
import com.quectel.core.module.scheduling.service.SchedulingAttendanceMonthService;
import com.quectel.util.common.DateUtils;
import com.quectel.util.kit.PageFetchKit;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.shardingsphere.elasticjob.api.ShardingContext;
import org.apache.shardingsphere.elasticjob.simple.job.SimpleJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author rananxin
 * @date 2021/11/18 7:24 下午
 */
@Component
public class SchedulingAttendanceMonthSummaryTask implements SimpleJob {

    private static final Logger LOGGER = LoggerFactory.getLogger(SchedulingAttendanceMonthSummaryTask.class);

    @DubboReference
    private SchedulingAttendanceGroupService schedulingAttendanceGroupService;
    @DubboReference
    private SchedulingAttendanceGroupPersonBindingService schedulingAttendanceGroupPersonBindingService;
    @DubboReference
    private SchedulingAttendanceDailyService schedulingAttendanceDailyService;
    @DubboReference
    private SchedulingAttendanceMonthService schedulingAttendanceMonthService;

    @Override
    public void execute(ShardingContext shardingContext) {
        summary();
    }

    /**
     * 考勤汇总
     */
    private void summary() {
        LOGGER.debug("开始考勤汇总");

        final Date currentDate = new Date();
        DateTime calDay = DateUtil.offsetDay(currentDate, -1);

        Map<String, Object> params = new HashMap<>();
        params.put(SystemConstants.TIME_SLOT_KEY_PAIR.getLeft(), DateUtils.format(DateUtil.beginOfMonth(calDay), DateUtils.FormatType.COMMON));
        params.put(SystemConstants.TIME_SLOT_KEY_PAIR.getRight(), DateUtils.format(DateUtil.endOfDay(calDay), DateUtils.FormatType.COMMON));
        List<SchedulingAttendanceDailyDto> schedulingAttendanceDailyDtos =
                PageFetchKit.fetchAll(req -> schedulingAttendanceDailyService.queryList(req), params, 500);
        Map<Long, List<SchedulingAttendanceDailyDto>> dailyGroupByPersonIdMap = schedulingAttendanceDailyDtos.parallelStream().collect(Collectors.groupingBy(SchedulingAttendanceDailyDto::getPersonId));
        for (Map.Entry<Long, List<SchedulingAttendanceDailyDto>> longListEntry : dailyGroupByPersonIdMap.entrySet()) {
            try {
                SchedulingAttendanceMonthDto schedulingAttendanceMonthDto = new SchedulingAttendanceMonthDto();
                schedulingAttendanceMonthDto.setPersonId(longListEntry.getKey());
                schedulingAttendanceMonthDto.setMonth(calDay);
                BigDecimal workOvertimeHour = BigDecimal.ZERO;
                BigDecimal leaveHour = BigDecimal.ZERO;
                BigDecimal tripHour = BigDecimal.ZERO;
                BigDecimal outHour = BigDecimal.ZERO;
                BigDecimal attendanceHour = BigDecimal.ZERO;
                BigDecimal realityAttendanceHour = BigDecimal.ZERO;

                int attendanceDay = 0;
                int realityAttendanceDay = 0;
                int lakeCount = 0;
                int lateCount = 0;
                int earlyCount = 0;
                for (SchedulingAttendanceDailyDto attendanceDailyDto : longListEntry.getValue()) {
                    workOvertimeHour = workOvertimeHour.add(Objects.nonNull(attendanceDailyDto.getWorkOvertimeHour()) ? attendanceDailyDto.getWorkOvertimeHour() : BigDecimal.ZERO);
                    leaveHour = leaveHour.add(Objects.nonNull(attendanceDailyDto.getLeaveHour()) ? attendanceDailyDto.getLeaveHour() : BigDecimal.ZERO);
                    tripHour = tripHour.add(Objects.nonNull(attendanceDailyDto.getTripHour()) ? attendanceDailyDto.getTripHour() : BigDecimal.ZERO);
                    outHour = outHour.add(Objects.nonNull(attendanceDailyDto.getOutHour()) ? attendanceDailyDto.getOutHour() : BigDecimal.ZERO);
                    attendanceHour = attendanceHour.add(Objects.nonNull(attendanceDailyDto.getAttendanceHour()) ? attendanceDailyDto.getAttendanceHour() : BigDecimal.ZERO);
                    realityAttendanceHour = realityAttendanceHour.add(Objects.nonNull(attendanceDailyDto.getRealityAttendanceHour()) ? attendanceDailyDto.getRealityAttendanceHour() : BigDecimal.ZERO);

                    if (SchedulingAttendanceDailyConstants.SituationTypeEnum.WORK.getType().equals(attendanceDailyDto.getSituation())
                            && CollectionUtils.isNotEmpty(attendanceDailyDto.getTimes())) {
                        attendanceDay++;

                        int dayLakeCount = 0;
                        for (int i = 0; i < attendanceDailyDto.getTimes().size(); i++) {
                            if (SchedulingAttendanceDailyConstants.TimeCheckStatusEnum.LATE.getStatus().equals(attendanceDailyDto.getTimes().get(0).getCheckWorkStatus())
                                    || SchedulingAttendanceDailyConstants.TimeCheckStatusEnum.LATE.getStatus().equals(attendanceDailyDto.getTimes().get(0).getCheckClosingStatus())) {
                                lateCount++;
                            }
                            if (SchedulingAttendanceDailyConstants.TimeCheckStatusEnum.EARLY.getStatus().equals(attendanceDailyDto.getTimes().get(0).getCheckWorkStatus())
                                    || SchedulingAttendanceDailyConstants.TimeCheckStatusEnum.EARLY.getStatus().equals(attendanceDailyDto.getTimes().get(0).getCheckClosingStatus())) {
                                earlyCount++;
                            }
                            if (SchedulingAttendanceDailyConstants.TimeCheckStatusEnum.LACK.getStatus().equals(attendanceDailyDto.getTimes().get(0).getCheckWorkStatus())
                                    || SchedulingAttendanceDailyConstants.TimeCheckStatusEnum.LACK.getStatus().equals(attendanceDailyDto.getTimes().get(0).getCheckClosingStatus())) {
                                lakeCount++;
                                dayLakeCount++;
                            }
                        }
                        if (dayLakeCount == 0) {
                            // 有缺卡
                            realityAttendanceDay++;
                        }
                    }
                }
                schedulingAttendanceMonthDto.setAttendanceHour(attendanceHour);
                schedulingAttendanceMonthDto.setRealityAttendanceHour(realityAttendanceHour);
                schedulingAttendanceMonthDto.setWorkOvertimeHour(workOvertimeHour);
                schedulingAttendanceMonthDto.setLeaveHour(leaveHour);
                schedulingAttendanceMonthDto.setTripHour(tripHour);
                schedulingAttendanceMonthDto.setOutHour(outHour);
                schedulingAttendanceMonthDto.setAttendanceDay(attendanceDay);
                schedulingAttendanceMonthDto.setRealityAttendanceDay(realityAttendanceDay);
                schedulingAttendanceMonthDto.setLakeCount(lakeCount);
                schedulingAttendanceMonthDto.setLateCount(lateCount);
                schedulingAttendanceMonthDto.setEarlyCount(earlyCount);

                schedulingAttendanceMonthService.saveOrUpdate(schedulingAttendanceMonthDto);
            } catch (Exception e) {
                LOGGER.error("Scheduling attendance summary error", e);
            }
        }
    }

}
